package org.bet.tools;

import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;
import org.apache.log4j.helpers.Loader;
import org.hedb.domain.GeneModelSet;
import org.hedb.domain.Genome;
import org.hedb.loader.AbstractGeneModelLoader;
import org.hedb.loader.AbstractGenomeLoader;
import org.hedb.loader.SyndicatedDataLoaderRegistry;
import org.hedb.loader.SyndicatedDataLoaderTargetEvent;
import org.hedb.loader.SyndicatedDataLoaderTargetListener;
import org.hedb.service.GeneModelService;
import org.hedb.service.GenomeService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class BatchDBUpdater {
	private static final String[] springLocations = {
		"/WEB-INF/main-context.xml",
	};

	private static BatchDBUpdater instance = null;

	private static final Logger logger = Logger.getLogger(BatchDBUpdater.class);
	
	private ApplicationContext applicationContext = null;
	private SyndicatedDataLoaderRegistry loaderRegistry = null;
	private AbstractGenomeLoader ncbiHumanGenomeLoader = null;
	private AbstractGeneModelLoader ucscGeneModelLoader = null;
	
	private GenomeService  genomeService = null;
	private GeneModelService geneModelService = null;
	

	
	public static BatchDBUpdater getInstance() throws Exception{
		if(instance == null){
			instance = new BatchDBUpdater();
			instance.init();
		}
		return instance;
	}
	
	private void init() throws Exception{
		PropertyConfigurator.configure(Loader.getResource("WEB-INF/log4j.properties"));
		
		applicationContext = new ClassPathXmlApplicationContext(springLocations);
		loaderRegistry = (SyndicatedDataLoaderRegistry) applicationContext.getBean("syndicatedDataLoaderRegistry");
		genomeService = (GenomeService) applicationContext.getBean("genomeService");
		geneModelService = (GeneModelService) applicationContext.getBean("geneModelService");
		
		ncbiHumanGenomeLoader = (AbstractGenomeLoader) loaderRegistry.getSyndicatedDataLoader(SyndicatedDataLoaderRegistry.LOADER_ID_NCBI_HG19);
		ncbiHumanGenomeLoader.addSyndicatedDataLoaderTargetListener(new SyndicatedDataLoaderTargetListener<Genome>() {
			
			@Override
			public void targetPrepared(SyndicatedDataLoaderTargetEvent<Genome> evt) {
			}
			
			@Override
			public void resourceLoaded(SyndicatedDataLoaderTargetEvent<Genome> evt) {
				Genome targetGenome = evt.getTarget();
				genomeService.saveOrUpdateGenome(targetGenome);
			}
			
			@Override
			public void allResourceLoaded(SyndicatedDataLoaderTargetEvent<Genome> evt) {
			}
		});
		
		ucscGeneModelLoader = (AbstractGeneModelLoader) loaderRegistry.getSyndicatedDataLoader(SyndicatedDataLoaderRegistry.LOADER_ID_UCSC_KNOWNGENE_HG19);
		ucscGeneModelLoader.addSyndicatedDataLoaderTargetListener(new SyndicatedDataLoaderTargetListener<GeneModelSet>() {
			@Override
			public void targetPrepared(SyndicatedDataLoaderTargetEvent<GeneModelSet> evt) {
				GeneModelSet target = evt.getTarget();
				geneModelService.saveOrUpdateGeneModelSet(target);				
			}

			@Override
			public void resourceLoaded(SyndicatedDataLoaderTargetEvent<GeneModelSet> evt) {
				GeneModelSet target = evt.getTarget();
				geneModelService.saveOrUpdateGeneModels(target.getGeneModels());
			}

			@Override
			public void allResourceLoaded(SyndicatedDataLoaderTargetEvent<GeneModelSet> evt) {
			}
			
		});
	}

	
	public final static String[] options = {"init.db.genome"};
	
	public static void main(String[] args) {
		if(ArrayUtils.isEmpty(args) || ArrayUtils.contains(options, args[0])){
			logger.info("Usage: java org.hedb.tools.BatchDBUpdater [init.db.genome | init.db.genes | init.db.all]");
		}
		
		try{
			BatchDBUpdater dbUpdater = BatchDBUpdater.getInstance();
			
			if(StringUtils.equalsIgnoreCase("init.db.genome", args[0])){
				dbUpdater.updateGenome();
			}
			if(StringUtils.equalsIgnoreCase("init.db.genes", args[0])){
				dbUpdater.updateGeneModels();
			}
		}
		catch(Exception e){
			logger.error(e);
		}
	}

	private void updateGeneModels() throws Exception{
		ucscGeneModelLoader.load();
	}

	private void updateGenome() throws Exception{
		ncbiHumanGenomeLoader.load();
	}
}
